package com.boilerCloud.dataSource;

import java.lang.reflect.Method;
import java.util.Arrays;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.boilerCloud.util.ParameterNameUtils;
import com.fasterxml.jackson.databind.ObjectMapper;

/** 
 * 方法拦截器，拦截Controller中的方法，记录log 
 * 
 */
@Component 
public class ControllerMethodInterceptor  implements MethodInterceptor {  
   private final Logger logger = LoggerFactory.getLogger(this.getClass());  
   //private final String str = "hh";  
      
    private final static ObjectMapper jsonMapper = new ObjectMapper();  
 


	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		// TODO Auto-generated method stub
		  String info = invocation.getMethod().getDeclaringClass()+ "." 
		+ invocation.getMethod().getName() + "()";            
				//System.out.println(info);

		logger.info("Before: interceptor name: {}",info);  
        logger.info("Arguments: {}", Arrays.toString(invocation.getArguments())); 
        Object[] arguments = invocation.getArguments();
        Method method = invocation.getMethod();
        printArgs(arguments, method);
        /*StringBuffer buff = new StringBuffer();
        for (int i = 0; i < arguments.length; i++) {
        	//System.out.println(arguments[i].getClass());
			if(!arguments[i].getClass().getName().contains("Request") && !arguments[i].getClass().getName().contains("Response")){
				buff.append(JSON.toJSONString(arguments[i]));
				buff.append(",");
			}
		}
        logger.info("Arguments: {}", buff.toString());  
*/
        Object result = invocation.proceed(); 
          
        logger.info("After: result: {}", result);  
          
        return result; 
	}  
	private void printArgs(Object[] args, Method method) {
		//StringBuffer buff = new StringBuffer();
		try {        
             String[] argNames = null;
             try {
                argNames = ParameterNameUtils.getMethodParamNames(method);
             } catch (Exception e) {
                error("获取参数名称异常：", e);
             }
              
            if (args != null) {
            	  String argName = null;
            	  String value = null;
            	  String argTypeName = null;
            	for (int i = 0; i < args.length; i++) {
            		argTypeName = args[i].getClass().getName();
                    if (argNames != null && argNames.length >= i) {
                         argName = argNames[i];
                    }
                    if(argTypeName.contains("Request") || argTypeName.contains("Response") || argTypeName.contains("MultipartFile")){
                    	info("【参数 {}={} 】", argName, argName);
                    	continue;
                    } 
                    if (args[i] != null) {
                    	try {
                             value = jsonMapper.writeValueAsString(args[i]);
                        } catch (Exception e) {
                             error("转换参数 \"{}\" 发生异常：", argName, e);
                        }
                        info("【参数 {}={} 】", argName, value);
                     } else {
                        info("参数 \"{}\"：NULL", argName);
                     }
                 }
              }
         } catch (Exception e) {
              error("【接口调用拦截器】打印方法执行参数异常：", e);
     }
     }
		     
	private void printResult(Object result) {
         if (result != null) {
             try {
                 info("【返回数据】：({})", jsonMapper.writeValueAsString(result));
            } catch (Exception e) {
                error("返回数据打印异常：", e);
            }
         } else {
             info("【返回数据】：NULL");
         }
     }
	     
     protected final void error(String msg, Object... objects) {
    	 logger.error(msg, objects);
	 }
	 
     protected final void info(String msg, Object... objects) {
    	 logger.info(msg, objects);
     }

} 
